/**
 * CompositionWindowDelegate.mm
 * @author Nick Kreeger <nick.kreeger@park.edu>
 */

#import "CompositionWindowDelegate.h"
#import "CompositionWindowController.h"

#import "NSString+Utils.h"

#import "CHMsgSendListener.h"
#import "CHMsgProgress.h"
#import "nsIMsgSend.h"
#import "nsIMsgCompose.h"
#import "nsIMsgComposeParams.h"
#import "nsMsgCompCID.h"

// Keep this here unless we need it elsewhere.
typedef enum {
  eToField,
  eCcField,
  eBccField,
  eSubjectField,
  eBodyField
} ECompFieldType;

@interface CompositionWindowDelegate(Private)

-(NSString*)compFieldStringForFieldType:(ECompFieldType)aCompFieldType;

@end

@implementation CompositionWindowDelegate

-(id)initWithComposerParams:(nsIMsgComposeParams*)aMsgComposeParams
{
  if ((self = [super init]))
  {
    NS_IF_ADDREF(aMsgComposeParams);
    mMsgComposeParams = aMsgComposeParams;
    mCompFieldsReady = NO;
    mCompBodyReady = NO;
    
    mMsgComposeWindow = new CHMsgComposeWindow();
    //mMsgComposeWindow->Init
    
    // Testing:
    char* uri;
    mMsgComposeParams->GetOriginalMsgURI(&uri);
    NSLog(@"uri = %s", uri);
    
    nsCOMPtr<nsIMsgCompFields> compFields;
    mMsgComposeParams->GetComposeFields(getter_AddRefs(compFields));
    
    nsAutoString geckoStr;
    compFields->GetSubject(geckoStr);
    NSLog(@"subject = %@", [NSString stringWith_nsAString:geckoStr]);
  }
  
  return self;
}

-(void)dealloc
{
  delete mMsgComposeWindow;
  [super dealloc];
}

-(void)setCompositionWindowController:(CompositionWindowController*)aCompWindowController
{
  mCompWindowController = aCompWindowController;
}

-(void)sendMessage
{
  /*
  nsresult rv;
  
  nsCOMPtr<nsIMsgIdentity> identity;
  mMsgComposeParams->GetIdentity(getter_AddRefs(identity));
  
  nsCOMPtr<nsIMsgCompFields> compFields;
  mMsgComposeParams->GetComposeFields(getter_AddRefs(compFields));
  
  //XXX this is setup for now, we need to be notified if the comp params
  //    have been modified.
  NSString* formattedToStr = [NSString commaSeparatedAddressStringFromSet:[mCompWindowController toContacts]];
  nsAutoString toStr;
  [formattedToStr assignTo_nsAString:toStr];
  compFields->SetTo(toStr);
  
  NSString* formattedCcStr = [NSString commaSeparatedAddressStringFromSet:[mCompWindowController ccContacts]];
  nsAutoString ccStr;
  [formattedCcStr assignTo_nsAString:ccStr];
  compFields->SetCc(ccStr);
  
  nsAutoString subjectStr;
  [[mCompWindowController subject] assignTo_nsAString:subjectStr];
  compFields->SetSubject(subjectStr);
  
  nsAutoString bodyStr; // remember, for 0.1 we are using text/plain
  // This is super hackey, but we need to make sure there is a new line ending
  // on the end of the body.
  NSString* bodyText = [mCompWindowController bodyText];
  if (![bodyText isEqualToString:@""] && [bodyText characterAtIndex:([bodyText length] - 1)] != '\n')
    bodyText = [bodyText stringByAppendingString:@"\n"];
    
  [bodyText assignTo_nsAString:bodyStr];
  compFields->SetBody(bodyStr);
  compFields->SetForcePlainText(PR_TRUE);
  
  // This is broken, so lets work around it with the nsIMsgProgress interface for now.
  CHMsgSendListener* sendListener = new CHMsgSendListener();
  sendListener->SetProgressDelegate(self);
  mMsgComposeParams->SetSendListener(sendListener);
  
  nsCOMPtr<nsIMsgCompose> msgCompose = do_CreateInstance(NS_MSGCOMPOSE_CONTRACTID, &rv);
  if (NS_FAILED(rv))
    return;  //XXX pose dialog?
  
  // We don't want to pass the DOM to the interface because it will modify the window
  // to be an editor, which we don't want.
  rv = msgCompose->Initialize(nsnull, mMsgComposeParams);
  if (NS_FAILED(rv))
    return;  //XXX pose dialog?
  
  // This is for now, it might be a good idea to combine nsIMsgProgress and nsIMsgSendListener
  CHMsgProgress* progress = new CHMsgProgress();
  progress->SetProgressDelegate(mCompWindowController);
  msgCompose->SendMsg(nsIMsgSend::nsMsgDeliverNow, identity, 
                      nsnull,  // accountKey
                      nsnull,  // msgWindow
                      progress); // nsIMsgProgress
   */
}

/**
 * Return the to addresses.
 * @return An NSSet with the to addresses, the set is autoreleased.
 *         Returns nil if there isn't any to addresses.
 */
-(NSSet*)toAddresses
{
  // This string might need to be cleaned up before seperating.
  NSString* addrStr = [self compFieldStringForFieldType:eToField];
  if (!addrStr)
    return nil;
  
  return [[NSSet setWithArray:[addrStr componentsSeparatedByString:@", "]] autorelease];
}

/**
 * Return the cc addresses.
 * @return An NSSet with the CC address, the set is autoreleased.
 *         Returns nil if there isn't any CC addresses.
 */
-(NSSet*)ccAddresses
{
  NSString* addrStr = [self compFieldStringForFieldType:eCcField];
  if (!addrStr)
    return nil;
  
  //XXX same as above...
  return [NSSet setWithArray:[addrStr componentsSeparatedByString:@", "]];
}

/**
 * Get the subject of the gecko comp field.
 * @return The NSString value of the subject, the string is autoreleased.
 *         Returns nil if there isn't a subject.
 */
-(NSString*)subject
{
  return [self compFieldStringForFieldType:eSubjectField];
}

/**
 * Get the body text of the gecko comp field.
 * @return The NSString value of the body text, the string is autoreleased.
 *         Returns nil if there isn't any body text.
 */
-(NSString*)bodyText
{
  return [self compFieldStringForFieldType:eBodyField];
}

/**
 * Get the composition type of the message (New, Reply-All, etc).
 * @return The composition type of the message.
 */
-(MSG_ComposeType)composeType
{
  MSG_ComposeType compType;
  nsIMsgComposeParams* msgComposeParams = mMsgComposeWindow->GetMsgComposeParams();
  msgComposeParams->GetType(&compType);
  
  return compType;
}

/**
 * Private utility function to convert a gecko string to a NSString
 * based upon the passed in |ECompFieldType|.
 * @param aCompFieldType The composition field to get the value from.
 * @return The NSString value from the specified field, string is autoreleased.
 *         Returns nil if there was not a value at the specified composition
 *         field, or if there was a problem accessing the value.
 */
-(NSString*)compFieldStringForFieldType:(ECompFieldType)aCompFieldType
{
  nsresult rv = NS_ERROR_FAILURE;  // assume fail, validate below
  nsIMsgComposeParams* msgComposeParams = mMsgComposeWindow->GetMsgComposeParams();
  nsCOMPtr<nsIMsgCompFields> compFields;
  msgComposeParams->GetComposeFields(getter_AddRefs(compFields));
  
  nsAutoString geckoStr;
  switch (aCompFieldType)
  {
    case eToField:
      rv = compFields->GetTo(geckoStr);
      break;
    case eCcField:
      rv = compFields->GetCc(geckoStr);
      break;
    case eSubjectField:
      rv = compFields->GetSubject(geckoStr);
      break;
    case eBodyField:
      rv = compFields->GetBody(geckoStr);
      break;
  }
  
  if (NS_FAILED(rv))
    return nil;
  
  return [[NSString stringWith_nsAString:geckoStr] autorelease];
}

#pragma mark -

//
// ComposerStateListenerDelegate implementation
//
-(void)onComposeFieldsReady
{
  mCompFieldsReady = YES;
  
  if (mCompBodyReady)
    [mCompWindowController showWindow:self];
}

-(void)onComposeProcessDone
{
}

-(void)onSaveInFolderDone:(NSString*)aFolderName
{
}

-(void)onComposeBodyReady
{
  mCompBodyReady = YES;
  
  if (mCompFieldsReady)
    [mCompWindowController showWindow:self];
}

@end

